import { defineStore } from "pinia";
import { reactive } from "vue";
import { useBasicInfoStore } from "./basicInfo";
import { getStorage, setStorage, toMap, toObj } from "@/utils";
import api from "@/api";

interface config {
  // 装备穿戴
  single_set: ID[]
  token: string
  carry_type: string
  // 贴膜列表
  fusion_list: ID[]
  // 触发列表
  trigger_set: Record<string, number[]>
  // 自定义
  customize: Record<string, number[]>
  // 武器贴膜
  merge: Record<string, number[]>
  // 怪物
  monster: number
  // 场景
  scene: number
  // 特性系统
  specificity_list: number[]
  alter: string
  // 打造
  forge_set: Record<string, Map<string, any>>
  // 时装
  dress_set: Record<string, { id?: number; option?: string }>
}

export const useConfigStore = defineStore("config", () => {
  const state = reactive<config>({
    single_set: [],
    token: "",
    carry_type: "",
    fusion_list: [],
    trigger_set: {},
    customize: {},
    merge: {},
    monster: 0,
    scene: 0,
    specificity_list: [],
    alter: "",
    forge_set: {},
    dress_set: {}
  });

  const infoStore = useBasicInfoStore()

  const toRefsValue = toRefs(state)

  const load = async () => {
    const alter = state.alter.split(".").pop() ?? "";
    let data = await getStorage<Object>(`dcalc/${alter}/sets`, {});
    // 本地无配置的时候的处理
    if (Object.keys(data).length == 0 || !data?.single_set || (data?.single_set ?? [])?.length == 0) {
      data = await api.defaultConfig(alter)
    }
    const temp = toMap(data, [
      "trigger_set",
      "customize",
      "buff_ratio",
      "dress_set",
      "corrections",
      "merge"
    ]) as config;

    infoStore.trigger_list?.forEach(trigger => {
      if (!temp.trigger_set[trigger.id.toString()]) {
        temp.trigger_set[trigger.id.toString()] = [0]
      } else {
        temp.trigger_set[trigger.id.toString()] = temp.trigger_set[trigger.id.toString()].map(Number)
      }
    })

    Object.keys(temp).forEach((key) => {
      if (Object.keys(state).includes(key)) {
        state[key] = temp[key];
      }
    });
  };

  const save = () => {
    const alter = state.alter.split(".").pop() ?? "";
    const temp = toObj(state)
    Reflect.deleteProperty(temp, "token")
    setStorage(`dcalc/${alter}/sets`, temp);
  };

  const calc = async () => {
    const temp = toObj(state) as any
    return await api.calc_m({
      single_set: temp.single_set,
      merge: temp.merge,
      fusion_list: temp.fusion_list,
      customize: temp.customize,
      specificity_list: temp.specificity_list,
      forge_set: temp.forge_set,
      dress_set: temp.dress_set,
      trigger_set: temp.trigger_set,
      carry_type: temp.carry_type,
      scene: temp.scene,
      monster: temp.monster
    });
  };

  const setForge = (part: string, key: string, value: any) => {
    if (!state.forge_set[part]) {
      state.forge_set[part] = new Map<string, any>();
    }
    const map = state.forge_set[part];
    map.set(key, value);
  };
  const getForge = (part: string, key: string) => {
    if (state.forge_set[part]) {
      const map = state.forge_set[part];
      return map.get(key);
    }
  };
  const setDress = (part: string, id: number, option: string) => {
    state.dress_set[part] = { id, option };
  };
  const getDress = (part: string) => {
    return state.dress_set[part];
  };

  const trimSingle = () => {
    const map = new Map<string, ID>()
    for (const id of state.single_set) {
      const equip = infoStore.getEquip(id)
      if (equip) {
        map.set(equip.part, id)
      }
    }
    state.single_set = [...map.values()].sort((a, b) => Number(a) - Number(b))
  }

  const addSingle = (id: ID, toggle = false) => {
    const newEquip = infoStore.getEquip(id)
    if (!newEquip) {
      return
    }
    if (toggle) {
      const index = state.single_set.indexOf(id)
      if (index > -1) {
        state.single_set.splice(index, 1)
        return
      }
    }
    state.single_set.push(id)
    trimSingle()
  }



  return {
    state,
    ...toRefsValue,
    load,
    save,
    calc,
    setForge,
    getForge,
    setDress,
    getDress,
    addSingle,
    trimSingle
  };
});
